/*
 * File:   funcSDLowLevel.h
 * Author: bram
 *
 * Created on February 23, 2013, 12:23 AM
 */

#ifndef FUNCSDLOWLEVEL_H
#define	FUNCSDLOWLEVEL_H

#include "types.h"

/* Definitions for MMC/SDC command */
#define CMD0   (0)			/* GO_IDLE_STATE */
#define CMD1   (1)			/* SEND_OP_COND */
#define ACMD41 (41|0x80)	/* SEND_OP_COND (SDC) */
#define CMD8   (8)			/* SEND_IF_COND */
#define CMD9   (9)			/* SEND_CSD */
#define CMD10  (10)			/* SEND_CID */
#define CMD12  (12)			/* STOP_TRANSMISSION */
#define ACMD13 (13|0x80)	/* SD_STATUS (SDC) */
#define CMD16  (16)			/* SET_BLOCKLEN */
#define CMD17  (17)			/* READ_SINGLE_BLOCK */
#define CMD18  (18)			/* READ_MULTIPLE_BLOCK */
#define CMD23  (23)			/* SET_BLOCK_COUNT */
#define ACMD23 (23|0x80)	/* SET_WR_BLK_ERASE_COUNT (SDC) */
#define CMD24  (24)			/* WRITE_BLOCK */
#define CMD25  (25)			/* WRITE_MULTIPLE_BLOCK */
#define CMD41  (41)			/* SEND_OP_COND (ACMD) */
#define CMD55  (55)			/* APP_CMD */
#define CMD58  (58)			/* READ_OCR */


#define CT_MMC				0x01
#define CT_SD1				0x02
#define CT_SD2				0x04
#define CT_SDC				(CT_SD1|CT_SD2)
#define CT_BLOCK			0x08


enum SDCMD {
    SDCMD_LOG = 1,
    SDCMD_FATFORMAT,
    SDCMD_START_LOG,
    SDCMD_END_LOG,
    SDCMD_RAW_READ,
    SDCMD_READ_CONFIG,
    SDCMD_WRITE_CONFIG
};


#define FAT_IDENT_SECTOR 0
#define FAT_IDENT_LENGTH 8

#define FAT_ENTRIES_SECTOR (FAT_IDENT_SECTOR + FAT_IDENT_LENGTH)
#define FAT_ENTRIES_LENGTH 2
#define FAT_ENTRIES_WEAR 128

#define FAT_CONFIG_SECTOR (FAT_ENTRIES_SECTOR + FAT_ENTRIES_LENGTH * FAT_ENTRIES_WEAR)
#define FAT_CONFIG_LENGTH 16
#define FAT_CONFIG_WEAR 128

#define FAT_ESC_FIRMWARE (FAT_CONFIG_SECTOR + FAT_CONFIG_LENGTH * FAT_CONFIG_WEAR)

#define SECTORS_PER_BLOCK       16 // 8kb blocks
#define BLOCK_SIZE          (SECTORS_PER_BLOCK * 512)

#define BLOCK_TO_SECTOR_OFFSET      32768
#define BLOCK_TO_SECTOR(block)   (block * SECTORS_PER_BLOCK + BLOCK_TO_SECTOR_OFFSET) // 8 kb blocks starting from 16 MB

struct SdCommand_t {
    BYTE type;
    void * ref;
};

struct SdCommandFileRange_t {
    int runID;
    int blockStart;
    int blockEnd;
    volatile BYTE done;
};

struct sdCommandReadSector_t {
    int sector;
    int length;
    BYTE * buffer;
    volatile BYTE done;
};

struct sdStatusStruct {
	unsigned int writeSuccess;
	unsigned int writeFailIRQ;
	unsigned int writeFailAccepted;
	unsigned int writeFailCmd;
	unsigned int writeFailCmdWait;
};

void TaskSD(void * params);
void sdRequestEndLog();
void sdRequestStartLog();
void sdStartDMARx(unsigned char * buff);
void sdStartDMATx(unsigned char * buff);
void sdReadConfig(unsigned char configLocation);
unsigned char sdReadSector(unsigned int sector, unsigned char * p, unsigned char sectorCount);
unsigned char sdWriteSector(unsigned int sector, unsigned char * buff, unsigned char sectorCount);
unsigned char sdInitCard();
unsigned char sdSendCmd(unsigned char cmd, unsigned int arg);
__inline unsigned char sdWriteReturn(unsigned char r);
unsigned char sdWaitReady();
unsigned char sdWriteSpi(unsigned char b);
UINT32 sdGetFreeBlock();
void sdMarkBlock(UINT32 block);
void sdReadFat(unsigned char fatLocation);



#endif	/* FUNCSDLOWLEVEL_H */

